iT邦幫忙

2023 iThome 鐵人賽

DAY 19
0

原本是想來介紹一下 SwiftData 和 Macro,不過這裡還沒更新到可以操作這兩個的版本,所以先改成來介紹一下別的東西吧。

那麼接下來介紹一下關於藍牙的部分,首先在 Swift 中關於藍牙的函式都是在 CoreBluetooth 之中,所以在使用前需要先 import 進來。

import CoreBluetooth

Central 的設定

接下來在正式開始之前要先來講解一下 CoreBluetooth 裡藍牙運作的方式,首先是藍牙裝置會被分成兩種:Central 跟 Peripheral,分別對應 App 端跟外部裝置,兩個分別處理的工作也不太一樣。

先來說 Central 的部分,也就是 App 端,主要的工作包含:掃描、連接外部藍牙裝置。

首先先指定一個變數,他的型別是 CBCentralManager,然後接下來,由於 BluetoothServices 這個檔案是在外部,我們需要寫一下這個 class 的啟動。

import Foundation
import CoreBluetooth

class BluetoothServices: NSObject {
    
    var central: CBCentralManager?
    
    private override init() {
        super.init()
    }
}

接下來是開始掃描、連接的部分,而 Central 工作的函式是由 CBCentralManagerDelegate 來處理,所以需要先 extension 進來。

extension 進來之後會報錯是正常的,因為它裡面有個函式是必須要呼叫的,按一下報錯訊息裡的 Fix,Xcode 會自己幫你加好。

extension BluetoothServices: CBCentralManagerDelegate {
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        
    }
}

新增函式的功能主要是在 Central 啟動時執行,或是在 State 有改變的時候執行,這裡的 State 是指手機端藍牙的狀態,這裡會判斷 State 來列印出對應的文字。

extension BluetoothServices: CBCentralManagerDelegate {
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .unknown:
            print("unknown")
        case .resetting:
            print("resetting")
        case .unsupported:
            print("unsupported")
        case .unauthorized:
            print("unauthorized")
        case .poweredOff:
            print("poweredOff")
        case .poweredOn:
            print("poweredOn")
        @unknown default:
            print("藍牙裝置未知狀態")
        }
    }
}

可以看到這裡藍牙裝置分為 6 種狀態,以及一種未知狀態。

到這裡都是啟動 Central 之後要做的事情,但是還沒決定什麼時候啟動,這裡由於我希望這個檔案啟動的時候也能同時啟動 Central,所以我們在上面已經寫好的 init 裡再多加一些東西。

private override init() {
    super.init()
        
    let quene = DispatchQueue.global()
    central = CBCentralManager(delegate: self, queue: quene)
}

到這裡為止,才真正算是設定好 Central 的部分,接下來是 Central 的工作。

Central 的工作

設定好之後,就是正式上工了。

首先,連接裝置之前需要知道有哪些外部裝置可以連接,這裡的程式很簡單,只需要一行就能讓 Central 開始掃描附近有哪些外部裝置可以連接。

central?.scanForPeripherals(withServices: nil)

接下來,又回到 CBCentralManagerDelegate 的部分,CBCentralManagerDelegate 裡有個函式是在 Central 發現裝置時執行的,我們需要在這裡去進行後續的處理。

func centralManager(_ central: CBCentralManager,
                    didDiscover peripheral: CBPeripheral,
                    advertisementData: [String : Any],
                    rssi RSSI: NSNumber) {
        
}

為了處理裝置,這裡先創建一個陣列用來儲存發現的外部裝置,然後在上面提到發現外部裝置時會執行的程式裡去處理。

private var blePeripherals: [CBPeripheral] = []

這裡每次執行時都會去判斷陣列裡有沒有這個外部裝置,如果沒有就會新增進去。

for newPeripheral in blePeripherals {
    if peripheral.name == newPeripheral.name {
        return
    }
}
        
if let name = peripheral.name {
    blePeripherals.append(peripheral)
    print(name)
}

掃描的部分都完成了,接下來是連接的部分,連接也很簡單,只需要將你要連接的裝置作為參數傳入。

func connectPeripheral(peripheral: CBPeripheral) {  
    central?.connect(peripheral, options: nil)
}

但是這樣還沒完全處理完,連接的裝置有了,但是這裡沒有東西處理連接之後的工作,需要回到 CBCentralManagerDelegate 裡做最後一件事。

這裡會將裝置的處理代理給這個檔案,並且開始之後的工作。

func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
    peripheral.delegate = self
    peripheral.discoverServices(nil)
}

那今天就先到這裡,明天來繼續處理 Peripheral 吧。


上一篇
Day 18:NavigationBar
下一篇
Day 20:CoreBluetooth(2)
系列文
SwiftUI學習之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言